package com.bnyy.medicalHousekeeper.moudle.message.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Base64;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.ScreenUtils;
import com.bnyy.common.EasyPhotosGlideEngine;
import com.bnyy.gbp.permission.PermissionHelper;
import com.bnyy.medicalHousekeeper.BuildConfig;
import com.bnyy.medicalHousekeeper.DialogHelper;
import com.bnyy.medicalHousekeeper.R;
import com.bnyy.medicalHousekeeper.UserInfoManager;
import com.bnyy.medicalHousekeeper.base.BaseActivityImpl;
import com.bnyy.medicalHousekeeper.moudle.message.AudioManager;
import com.bnyy.medicalHousekeeper.moudle.message.ChatManager;
import com.bnyy.medicalHousekeeper.moudle.message.MessageManager;
import com.bnyy.medicalHousekeeper.moudle.message.adapter.ChatMessageAdapter;
import com.bnyy.medicalHousekeeper.request.BaseObserverImpl;
import com.bnyy.medicalHousekeeper.request.RequestManager;
import com.bnyy.message.bean.Contact;
import com.bnyy.message.bean.ContactGroup;
import com.bnyy.message.bean.ContactUser;
import com.bnyy.message.bean.GroupChatSetting;
import com.bnyy.message.bean.Message;
import com.bnyy.message.bean.chat.Chat;
import com.bnyy.message.bean.chat.ChatInfo;
import com.bnyy.message.bean.chat.ChatMessage;
import com.bnyy.message.bean.chat.SendingChatMessage;
import com.bnyy.message.enums.ChatMessageStatus;
import com.bnyy.message.enums.ChatType;
import com.bnyy.message.enums.GroupChatIdentity;
import com.bnyy.message.enums.MessageType;
import com.bnyy.message.event.ErrorMessageEvent;
import com.bnyy.message.event.ReceiveMessageEvent;
import com.bnyy.message.event.SendMessageEvent;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.huantansheng.easyphotos.EasyPhotos;
import com.huantansheng.easyphotos.callback.SelectCallback;
import com.huantansheng.easyphotos.models.album.entity.Photo;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BasePopupView;
import com.scwang.smart.refresh.layout.SmartRefreshLayout;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.listener.OnRefreshListener;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import butterknife.BindView;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import top.zibin.luban.CompressionPredicate;
import top.zibin.luban.Luban;
import top.zibin.luban.OnCompressListener;

import static android.media.MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED;

/**
 * Author : 关炳鹏
 * Description :
 * Date : 2022/6/29
 **/
public class ChatMessageActivity extends BaseActivityImpl {
    @BindView(R.id.recycler_view)
    RecyclerView recyclerView;
    @BindView(R.id.iv)
    ImageView iv;
    @BindView(R.id.et)
    EditText et;
    @BindView(R.id.tv_record_audio)
    TextView tvRecordAudio;
    @BindView(R.id.refresh_layout)
    SmartRefreshLayout refreshLayout;
    @BindView(R.id.iv_emoji)
    ImageView ivEmoji;
    @BindView(R.id.iv_add)
    ImageView ivAdd;
    @BindView(R.id.tv_album)
    TextView tvAlbum;
    @BindView(R.id.tv_take_photo)
    TextView tvTakePhoto;
    @BindView(R.id.ll_options)
    LinearLayout llOptions;
    @BindView(R.id.ll_operate)
    LinearLayout llOperate;
    @BindView(R.id.tv_group_chat_notice)
    TextView tvGroupChatNotice;
    @BindView(R.id.tv_vote)
    TextView tvVote;
    @BindView(R.id.tv_launch_activity)
    TextView tvLaunchActivity;

    private ChatMessageAdapter adapter;
    public Chat chat;
    private ActivityResultLauncher<Intent> atLauncher;
    private ArrayList<ContactGroup.Member> atMembers = new ArrayList<>();
    private String contentBeforeEdit = "";
    private boolean at = false;
    private int maxInput = 300;

    /**
     * @param context
     * @param contact userId 或 groupChatId
     */
    public static void show(Context context, Contact contact) {
        if (contact instanceof ContactUser) {
            show(context, new Chat(UserInfoManager.getInstance().getLoginUserId(), contact.getId(), contact.getRole_id()));
        } else {
            show(context, new Chat(UserInfoManager.getInstance().getLoginUserId(), contact.getId()));
        }
    }

    public static void show(Context context, Chat chat) {
        ChatManager.getChat(context, chat, new Consumer<Chat>() {
            @Override
            public void accept(Chat chat) {
                Intent intent = new Intent(context, ChatMessageActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.putExtra("chat", chat);
                context.startActivity(intent);
            }
        });
    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_chat_message;
    }

    @Override
    public String getTitleStr() {
        return null;
    }

    @Override
    public boolean registerEventBus() {
        return true;
    }

    @Override
    public boolean unuseRefreshLayout() {
        return true;
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initEditText();

        initOptions(true);

        iv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean tag = (boolean) v.getTag();
                if (tag) {
                    iv.setImageResource(R.mipmap.icon_chat_keyboard);
                    et.setVisibility(View.GONE);
                    tvRecordAudio.setVisibility(View.VISIBLE);
                } else {
                    iv.setImageResource(R.mipmap.icon_chat_audio);
                    et.setVisibility(View.VISIBLE);
                    tvRecordAudio.setVisibility(View.GONE);
                }
                iv.setTag(!tag);
            }
        });

        tvAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PermissionHelper.getInstance().requestPermission(new PermissionHelper.RequestPermission() {
                    @Override
                    public String[] permissions() {
                        return new String[]{
                                Manifest.permission.WRITE_EXTERNAL_STORAGE
                        };
                    }

                    @Override
                    public void granted(HashSet<String> granted) {
                        EasyPhotos.createAlbum(mContext, false, false, EasyPhotosGlideEngine.getInstance())
                                .setPuzzleMenu(false)
                                .setCount(9)//参数说明：最大可选数，默认1
                                .start(new SelectCallback() {
                                    @Override
                                    public void onResult(ArrayList<Photo> photos, boolean isOriginal) {
                                        dealPhotos(photos);
                                    }

                                    @Override
                                    public void onCancel() {

                                    }
                                });
                    }

                    @Override
                    public void denied(HashSet<String> denied) {
                        DialogHelper.showTipsDialog(mContext, "请手动打开读写内存权限");
                    }
                });
            }
        });
        tvTakePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EasyPhotos.createCamera(mContext, true)
                        .setFileProviderAuthority(BuildConfig.APPLICATION_ID + ".fileprovider")
                        .start(new SelectCallback() {
                            @Override
                            public void onResult(ArrayList<Photo> photos, boolean isOriginal) {
                                dealPhotos(photos);
                            }

                            @Override
                            public void onCancel() {

                            }
                        });
            }
        });

        tvVote.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                GroupChatVotesActivity.show(mContext, chat.getRecipientId());
            }
        });

        tvLaunchActivity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                GroupChatActivitiesActivity.show(mContext, chat.getRecipientId());
            }
        });

        ivAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (llOptions.getVisibility() == View.VISIBLE) {
                    llOptions.setVisibility(View.GONE);
                } else {
                    llOptions.setVisibility(View.VISIBLE);
                }
            }
        });

        tvRecordAudio.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        if (PermissionHelper.checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO)) {
                            tvRecordAudio.setText("松开结束");
                            showRecordAudioDialog();

                            File parent = new File(getExternalCacheDir(), "/audio");
                            if (!parent.exists()) {
                                parent.mkdir();
                            }
                            File file = new File(parent, System.currentTimeMillis() + ".amr");

                            tvRecordAudio.setTag(file.getAbsolutePath());

                            mediaRecorder = new MediaRecorder();
                            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
                            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                            mediaRecorder.setMaxDuration(MessageManager.MAX_AUDIO_DURATION);
                            mediaRecorder.setOutputFile(file);
                            mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
                                @Override
                                public void onInfo(MediaRecorder mr, int what, int extra) {
                                    if (what == MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
                                        recordFinish();
                                    }
                                }
                            });
                            try {
                                mediaRecorder.prepare();
                                mediaRecorder.start();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        } else {
                            PermissionHelper.getInstance().requestPermission(new PermissionHelper.RequestPermission() {
                                @Override
                                public String[] permissions() {
                                    return new String[]{
                                            Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                            Manifest.permission.RECORD_AUDIO
                                    };
                                }

                                @Override
                                public void granted(HashSet<String> granted) {

                                }

                                @Override
                                public void denied(HashSet<String> denied) {

                                }
                            });
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        recordFinish();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (recordAudioDialog != null && recordAudioDialog.isShowing()) {
                            if (event.getY() < 0) {
                                if (!cancelRecordAudio) {
                                    if (recordAudioDialog != null) {
                                        Window window = recordAudioDialog.getWindow();
                                        if (window != null) {
                                            View root = window.getDecorView().findViewById(R.id.ll_root);
                                            GradientDrawable gradientDrawable = (GradientDrawable) root.getBackground();
                                            gradientDrawable.setColor(Color.parseColor("#FF6E73"));
                                            ImageView iv = root.findViewById(R.id.iv);
                                            iv.setImageResource(R.mipmap.icon_chat_audio_withdraw_big);
                                            root.findViewById(R.id.ll_voice).setVisibility(View.GONE);

                                            TextView tvTips = root.findViewById(R.id.tv_tips);
                                            tvTips.setCompoundDrawables(null, null, null, null);
                                            tvTips.setText("松开手指，取消发送");
                                        }
                                    }
                                    cancelRecordAudio = true;
                                }
                            } else {
                                if (cancelRecordAudio) {
                                    if (recordAudioDialog != null) {
                                        Window window = recordAudioDialog.getWindow();
                                        if (window != null) {
                                            View root = window.getDecorView().findViewById(R.id.ll_root);
                                            GradientDrawable gradientDrawable = (GradientDrawable) root.getBackground();
                                            gradientDrawable.setColor(Color.parseColor("#80000000"));
                                            ImageView iv = root.findViewById(R.id.iv);
                                            iv.setImageResource(R.mipmap.icon_chat_mic);
                                            root.findViewById(R.id.ll_voice).setVisibility(View.VISIBLE);

                                            TextView tvTips = root.findViewById(R.id.tv_tips);
                                            Drawable drawable = getResources().getDrawable(R.mipmap.icon_chat_audio_withdraw);
                                            drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
                                            tvTips.setCompoundDrawables(drawable, null, null, null);
                                            tvTips.setText("手指上划，取消发送");
                                        }
                                    }
                                    cancelRecordAudio = false;
                                }
                            }
                        }
                        break;
                }
                return true;
            }
        });

        refreshLayout.setEnableLoadMore(false);
        refreshLayout.setEnableOverScrollDrag(true);
        refreshLayout.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh(@NonNull RefreshLayout refreshLayout) {

                int itemCount = adapter.getItemCount();
                if (itemCount > 0) {
                    ArrayList<ChatMessage> chatMessages = MessageManager.loadMoreChatMessages(chat.getChatId(), adapter.getDatas().get(0).getTime());
                    if (chatMessages.size() > 0) {
                        adapter.getDatas().addAll(0, chatMessages);
                        adapter.notifyDataSetChanged();
                    } else {
                        refreshLayout.setEnableRefresh(false);
                    }
                    refreshLayout.finishRefresh();
                } else {
                    refreshLayout.finishRefresh();
                    refreshLayout.setEnableRefresh(false);
                }
            }
        });
        refreshLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                refreshLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                refreshLayout.getRefreshHeader().getView().setVisibility(View.INVISIBLE);
            }
        });

        recyclerView.setItemAnimator(null);
        recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
        recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);

        ActivityResultLauncher<Intent> addGroupChatMemberLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        Intent data = result.getData();
                        if (data != null) {
                            ArrayList<Contact> contacts = (ArrayList<Contact>) data.getSerializableExtra(SelectContactActivity.RESULT_SELECTED_CONTACTS);
                            if (contacts != null && contacts.size() > 0) {
                                HashMap<String, Object> params = new HashMap<>();
                                params.put("id", chat.getRecipientId());
                                ArrayList<HashMap<String, Integer>> users = new ArrayList<>();
                                contacts.forEach(new Consumer<Contact>() {
                                    @Override
                                    public void accept(Contact contact) {
                                        HashMap<String, Integer> map = new HashMap<>();
                                        map.put("id", contact.getId());
                                        map.put("role_id", contact.getRole_id());
                                        users.add(map);
                                    }
                                });
                                params.put("user_id", userInfoManager.getLoginUserId());
                                params.put("users", users);

                                requestManager.request(requestManager.mMessageRetrofitService.addGroupChatMember(RequestManager.getJsonRequestBody(params)),
                                        new BaseObserverImpl<Object>(mContext) {
                                            @Override
                                            public void onSuccess() {
                                                super.onSuccess();
                                                init();
                                            }
                                        });
                            }
                        }
                    }
                });

        adapter = new ChatMessageAdapter(mContext, new ChatMessageAdapter.Callback() {
            @Override
            public void resendMessage(String msgId) {
                SendingChatMessage sendingChatMessage = MessageManager.getSendingChatMessage(msgId);
                if (sendingChatMessage != null) {
                    sendMessage(new Gson().fromJson(sendingChatMessage.getMessage(), ChatMessage.class));
                }
            }

            @Override
            public void editGroupChatName() {
                HashMap<String, Object> params = new HashMap<>();
                params.put("id", chat.getRecipientId());
                requestManager.request(requestManager.mMessageRetrofitService.getGroupChatSetting(RequestManager.getJsonRequestBody(params)),
                        new BaseObserverImpl<GroupChatSetting>(mContext) {
                            @Override
                            public void onSuccess(GroupChatSetting groupChatSetting) {
                                super.onSuccess(groupChatSetting);
                                EditGroupChatNameActivity.show(mContext, groupChatSetting.getId(), groupChatSetting.getGroup_name());
                            }
                        });
            }

            @Override
            public void addMember() {
                HashMap<String, Object> params = new HashMap<>();
                params.put("id", chat.getRecipientId());
                requestManager.request(requestManager.mMessageRetrofitService.getGroupChatSetting(RequestManager.getJsonRequestBody(params)),
                        new BaseObserverImpl<GroupChatSetting>(mContext) {
                            @Override
                            public void onSuccess(GroupChatSetting groupChatSetting) {
                                super.onSuccess(groupChatSetting);
                                requestManager.request(requestManager.mMessageRetrofitService.getFriendList(),
                                        new BaseObserverImpl<ArrayList<ContactUser>>(mContext) {
                                            @Override
                                            public void onSuccess(ArrayList<ContactUser> contactUsers) {
                                                super.onSuccess(contactUsers);
                                                HashSet<Integer> memberIds = new HashSet<>();

                                                ArrayList<ContactUser> target = new ArrayList<>();
                                                if (contactUsers != null && contactUsers.size() > 0) {
                                                    for (ContactGroup.Member member : groupChatSetting.getUser_list()) {
                                                        memberIds.add(member.getId());
                                                    }

                                                    for (ContactUser contactUser : contactUsers) {
                                                        if (!memberIds.contains(contactUser.getId())) {
                                                            target.add(contactUser);
                                                        }
                                                    }
                                                }
                                                SelectContactActivity.show(
                                                        mContext,
                                                        "添加群成员",
                                                        "确认要添加选中的好友吗",
                                                        false,
                                                        true,
                                                        null,
                                                        target,
                                                        addGroupChatMemberLauncher
                                                );
                                            }
                                        });
                            }
                        });
            }
        });
        recyclerView.setAdapter(adapter);

        onNewIntent(getIntent());
    }

    private void initEditText() {
        et.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxInput)});

        atLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
                new ActivityResultCallback<ActivityResult>() {
                    @Override
                    public void onActivityResult(ActivityResult result) {
                        Intent intent = result.getData();
                        if (intent != null) {
                            atMembers = (ArrayList<ContactGroup.Member>) intent.getSerializableExtra("atMembers");

                            if (atMembers != null) {
                                if (atMembers.size() > 0) {
                                    String s = et.getText().toString();
                                    char[] chars = s.toCharArray();
                                    int selectionEnd = et.getSelectionEnd(); // 获取光标位置
                                    int remain = chars.length - selectionEnd;
                                    StringBuilder sbAt = new StringBuilder();
                                    for (int i = 0; i < atMembers.size(); i++) {
                                        if (i != 0) {
                                            sbAt.append("@");
                                        }
                                        sbAt.append(atMembers.get(i).getUsername()).append(" ");
                                    }

                                    if (sbAt.length() + chars.length > maxInput) {
                                        sbAt.delete(maxInput - chars.length, sbAt.length() - 1);
                                    }

                                    StringBuilder sb = new StringBuilder();
                                    for (int i = 0; i < selectionEnd; i++) { // 光标前的内容
                                        sb.append(chars[i]);
                                    }

                                    sb.append(sbAt);

                                    if (chars.length > selectionEnd) {
                                        for (int i = selectionEnd; i < chars.length; i++) {// 光标后的内容
                                            sb.append(chars[i]);
                                        }
                                    }
                                    at = true;
                                    et.setText(sb.toString());
                                    if (remain > 0) {
                                        et.setSelection(sb.length() - remain);
                                    } else {
                                        et.setSelection(sb.length());
                                    }
                                    at = false;
                                }
                            }
                        }
                    }
                });

        et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                llOptions.setVisibility(View.GONE);
            }
        });
        et.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == 67 && event.getAction() == 0) { // 监听回退键按下
                    Editable text = et.getText();

                    if (TextUtils.isEmpty(text)) {
                        return false;
                    } else {
                        if (chat != null) {
                            if (chat.getChatType() == ChatType.GROUP_CHAT) {
                                String s = text.toString();
                                if (s.contains("@")) { // 删除带@的内容
                                    char[] chars = s.toCharArray();
                                    int selectionEnd = et.getSelectionEnd();
                                    int remain = chars.length - selectionEnd;
                                    if (chars[selectionEnd - 1] == ' ') { // 如果删除的光标定位再空格后
                                        for (int i = selectionEnd - 2; i >= 0; i--) {
                                            if (chars[i] == '@') { // 获取到离空格最近一个@
                                                StringBuilder sb = new StringBuilder();
                                                // 保留@之前的内容
                                                for (int j = 0; j < i; j++) {
                                                    sb.append(chars[j]);
                                                }
                                                // 保留空格之后的内容
                                                for (int k = selectionEnd; k < chars.length; k++) {
                                                    sb.append(chars[k]);
                                                }

                                                at = true;
                                                et.setText(sb.toString());
                                                if (remain > 0) {
                                                    et.setSelection(sb.length() - remain);
                                                } else {
                                                    et.setSelection(sb.length());
                                                }
                                                at = false;
                                                break;
                                            }
                                        }
                                        return true;
                                    }
                                }
                            }
                        }
                        return false;
                    }
                } else if (keyCode == 66 && event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (TextUtils.isEmpty(et.getText())) {
                        Toast.makeText(mContext, "不能发送空消息", Toast.LENGTH_SHORT).show();
                    } else {
                        String content = et.getText().toString();
                        ChatMessage chatMessage = new ChatMessage(chat, userInfoManager.getLoginUserInfo(), MessageType.CHAT_TEXT, content);

                        if (atMembers != null && atMembers.size() > 0) {

                            chatMessage.setAt_ids(atMembers.stream()
                                    .filter(new Predicate<ContactGroup.Member>() {
                                        @Override
                                        public boolean test(ContactGroup.Member member) {
                                            return content.contains(member.getUsername());
                                        }
                                    })
                                    .map(ContactGroup.Member::getId)
                                    .distinct()
                                    .collect(Collectors.toCollection(ArrayList::new)));

                            atMembers.clear();
                        }
                        sendMessage(chatMessage);
                        et.setText("");
                    }
                    return true;
                }
                return false;
            }
        });

        et.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                if (TextUtils.isEmpty(s)) {
                    contentBeforeEdit = "";
                } else {
                    contentBeforeEdit = s.toString();
                }
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!at) { // at之后设置文本忽略处理
                    if (chat != null) {
                        if (chat.getChatType() == ChatType.GROUP_CHAT) {
                            if (!TextUtils.isEmpty(s)) {
                                if (s.length() > contentBeforeEdit.length()) { // 只有在增加文本的时候会触发at，删除不触发
                                    char[] chars = s.toString().toCharArray();
                                    if (chars[et.getSelectionStart() - 1] == '@') {
                                        AtGroupChatMemberActivity.show(mContext, chat.getRecipientId(), atLauncher);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    private void initOptions(boolean enable) {
        if (enable) {
            TextView tv = new TextView(mContext);
            Drawable drawable = getResources().getDrawable(R.mipmap.icon_options);
            drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
            tv.setCompoundDrawables(drawable, null, null, null);
            tv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    switch (chat.getChatType()) {
                        case STRANGER:
                        case PRIVATE_CHAT:
                            PrivateChatSettingActivity.show(mContext, chat.getRecipientId(), chat.getRecipientRoleId());
                            break;
                        case GROUP_CHAT:
                            GroupChatSettingActivity.show(mContext, chat);
                            break;
                    }
                }
            });
            setOptions(tv);
        } else {
            setOptions();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        chat = (Chat) intent.getSerializableExtra("chat");

        iv.setTag(true);
        iv.setImageResource(R.mipmap.icon_chat_audio);
        tvRecordAudio.setVisibility(View.GONE);
        et.setVisibility(View.VISIBLE);
        et.setText("");

        if (adapter != null) {
            adapter.refresh(new ArrayList<>());
        }

        if (chat != null) {
            ChatInfo chatInfo = chat.getChatInfo();
            if (chatInfo != null) {
                setTitleStr(chatInfo.getChatName());
            }
            switch (chat.getChatType()) {
                case STRANGER:
                case PRIVATE_CHAT:
                    break;
                case GROUP_CHAT:
                    tvVote.setVisibility(View.VISIBLE);

                    if (chat.getContactUsers().size() == 0) {
                        llOperate.setVisibility(View.GONE);
                        initOptions(false);
                        Toast.makeText(mContext, "群聊已解散", Toast.LENGTH_SHORT).show();
                    }

                    break;
            }

            refresh();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        ArrayList<ChatMessage> datas = adapter.getDatas();
        if (datas.size() > 0) {
            ChatMessage chatMessage = MessageManager.getChatMessage(datas.get(0).getMsgId());
            if (chatMessage == null) {
                refresh();
            }
        }
        if (chat.getChatType() == ChatType.GROUP_CHAT) {
            init();
        }
    }

    private void refresh() {
        MessageManager.clearUnreadCount(chat);

        showGroupChatNotice(MessageManager.getGroupChatNotice(chat.getChatId()));

        ArrayList<ChatMessage> latestChatRecords = MessageManager.getLatestChatMessages(chat.getChatId());
        adapter.refresh(latestChatRecords);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                recyclerView.scrollToPosition(adapter.getItemCount() - 1);
            }
        }, 100);
    }

    private void init() {
        HashMap<String, Object> params = new HashMap<>();
        params.put("id", chat.getRecipientId());
        requestManager.request(requestManager.mMessageRetrofitService.getGroupChatSetting(RequestManager.getJsonRequestBody(params)),
                new BaseObserverImpl<GroupChatSetting>() {
                    @Override
                    public void onSuccess(GroupChatSetting groupChatSetting) {
                        super.onSuccess(groupChatSetting);

                        if (groupChatSetting.getGroup_type() == 2) {
                            tvLaunchActivity.setVisibility(View.VISIBLE);
                        }

                        ArrayList<ContactGroup.Member> members = groupChatSetting.getUser_list();

                        setTitleStr(groupChatSetting.getGroup_name() + "（" + members.size() + "）");

                        boolean removed = true; // 是否被移除
                        for (ContactGroup.Member member : members) {
                            if (member.getId() == userInfoManager.getLoginUserId()) {
                                removed = false;
                            }
                        }
                        if (removed) {
                            llOperate.setVisibility(View.GONE);
                            initOptions(false);
                        } else {
                            GroupChatSetting.GroupChatManage groupAdmin = groupChatSetting.getGroup_admin();

                            if (groupAdmin.isProhibit_chat()) {
                                if (groupChatSetting.getGroupChatIdentity() == GroupChatIdentity.MEMBER) {
                                    llOperate.setVisibility(View.GONE);
                                }
                            } else {
                                llOperate.setVisibility(View.VISIBLE);
                                initOptions(true);
                            }
                        }
                    }
                });
    }

    private LinkedList<Photo> photoQueue = new LinkedList<>();

    private void dealPhotos(ArrayList<Photo> photos) {
        if (photos != null && photos.size() > 0) {
            photoQueue.addAll(photos);
            executeDealPhoto();
        }
    }

    private void executeDealPhoto() {
        if (photoQueue.size() > 0) {
            Photo photo = photoQueue.poll();
            if (photo == null) {
                executeDealPhoto();
            } else {
                BasePopupView popupView = new XPopup.Builder(mContext)
                        .asLoading()
                        .show();
                compressImage(photo.path, 1024 * 2, new OnCompressFinishListener() {
                    @Override
                    public void onSuccess(File file) {
                        uploadImage(file, new OnUploadFinishListener() {
                            @Override
                            public void onSuccess(String url) {

                                compressImage(file.getAbsolutePath(), 100, new OnCompressFinishListener() {
                                    @Override
                                    public void onSuccess(File file) {
                                        byte[] bytes = FileIOUtils.readFile2BytesByStream(file);
                                        String content = Base64.encodeToString(bytes, Base64.DEFAULT);
                                        ChatMessage chatMessage = new ChatMessage(chat, userInfoManager.getLoginUserInfo(), MessageType.CHAT_IMAGE, content);

                                        BitmapFactory.Options options = new BitmapFactory.Options();

                                        options.inJustDecodeBounds = true;

                                        BitmapFactory.decodeFile(photo.path, options);

                                        options.inSampleSize = 1;

                                        options.inJustDecodeBounds = false;

                                        chatMessage.setW(options.outWidth);
                                        chatMessage.setH(options.outHeight);

                                        String imageCachePath = MessageManager.getImageCachePath(content);
                                        FileUtils.copy(file, new File(imageCachePath));

                                        chatMessage.setImageCachePath(imageCachePath);
                                        chatMessage.setOriginalImageUrl(url);

                                        sendMessage(chatMessage);

                                        popupView.delayDismissWith(100, new Runnable() {
                                            @Override
                                            public void run() {
                                                executeDealPhoto();
                                            }
                                        });
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                        popupView.delayDismissWith(100, new Runnable() {
                                            @Override
                                            public void run() {
                                                executeDealPhoto();
                                            }
                                        });
                                    }
                                });

                            }

                            @Override
                            public void onError(Throwable e) {
                                popupView.delayDismissWith(100, new Runnable() {
                                    @Override
                                    public void run() {
                                        executeDealPhoto();
                                    }
                                });
                            }
                        });
                    }

                    @Override
                    public void onError(Throwable e) {
                        popupView.delayDismissWith(100, new Runnable() {
                            @Override
                            public void run() {
                                executeDealPhoto();
                            }
                        });
                    }
                });
            }
        }
    }

    public void compressImage(String imagePath, int ignoreBy, OnCompressFinishListener l) {
        Luban.with(this)
                .load(imagePath)
                .ignoreBy(ignoreBy)
                .filter(new CompressionPredicate() {
                    @Override
                    public boolean apply(String path) {
                        return !(TextUtils.isEmpty(path) || path.toLowerCase().endsWith(".gif"));
                    }
                })
                .setCompressListener(new OnCompressListener() {
                    @Override
                    public void onStart() {
                    }

                    @Override
                    public void onSuccess(File file) {
                        l.onSuccess(file);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(mContext, "图片压缩失败，请重试", Toast.LENGTH_SHORT).show();
                        l.onError(e);
                    }
                }).launch();
    }

    public void uploadImage(File file, OnUploadFinishListener l) {
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        try {
            builder.addFormDataPart("files", URLEncoder.encode(file.getName(), "UTF-8"), requestBody);//files 文件上传参数
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        List<MultipartBody.Part> parts = builder.build().parts();
        requestManager.request(requestManager.mRetrofitServiceServer.uploadFiles(parts),
                new BaseObserverImpl<LinkedTreeMap<String, String[]>>() {
                    @Override
                    public void onSuccess(LinkedTreeMap<String, String[]> linkedTreeMap) {
                        super.onSuccess(linkedTreeMap);
                        String[] strings = linkedTreeMap.get("fiels");
                        if (strings != null && strings.length > 0) {
                            l.onSuccess(strings[0]);
                        } else {
                            l.onError(new Exception());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                        Toast.makeText(mContext, "图片上传失败，请重试", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    private void sendMessage(ChatMessage chatMessage) {
        if (chat.isStrangerChat()) {
            MessageManager.deleteStrangerChat(chat.getChatId());
            chat.setType(ChatType.PRIVATE_CHAT.getType());
        }
        MessageManager.sendChatMessage(chatMessage);

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                SendingChatMessage sendingChatMessage = MessageManager.getSendingChatMessage(chatMessage.getMsgId());
                if (sendingChatMessage != null) {
                    ArrayList<ChatMessage> chatMessages = adapter.getDatas();
                    int size = chatMessages.size();
                    for (int i = 0; i < size; i++) {
                        ChatMessage data = chatMessages.get(i);

                        if (data.getMsgId().equals(sendingChatMessage.getMsgId())) {
                            int finalI = i;
                            new Handler(Looper.getMainLooper()).post(new Runnable() {
                                @Override
                                public void run() {
                                    data.setChatMessageStatus(ChatMessageStatus.FAILURE);
                                    adapter.notifyItemChanged(finalI);
                                }
                            });
                            break;
                        }
                    }
                }

            }
        }, 30 * 1000);
    }

    @Override
    protected void onPause() {
        super.onPause();
        AudioManager.getInstance().stop();
    }

    private MediaRecorder mediaRecorder;
    private boolean cancelRecordAudio = false;
    private AlertDialog recordAudioDialog, recordAudioTipsDialog;
    private Timer voiceTimer;
    private int voiceLevel = 7;
    private int minVoice = 5;

    private void showRecordAudioDialog() {
        if (recordAudioDialog == null) {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            View root = inflater.inflate(R.layout.dialog_chat_record_audio, null);
            GradientDrawable gradientDrawable = new GradientDrawable();
            gradientDrawable.setColor(Color.parseColor("#80000000"));
            gradientDrawable.setCornerRadius(20);
            root.setBackground(gradientDrawable);

            LinearLayout llVoice = root.findViewById(R.id.ll_voice);
            int voiceWidth = ScreenUtils.getScreenWidth() / voiceLevel;
            int height = voiceWidth / 10;
            for (int i = 0; i < voiceLevel; i++) {
                View view = new View(mContext);
                view.setId(i);
                ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(voiceWidth - (i * (voiceWidth / 3 * 2 / voiceLevel)), height);
                if (i == voiceLevel - 1) {
                    view.setBackgroundColor(Color.WHITE);
                } else {
                    marginLayoutParams.bottomMargin = height;
                    view.setBackgroundColor(Color.parseColor("#80FAFAFA"));
                }
                llVoice.addView(view, marginLayoutParams);
            }
            builder.setView(root);
            recordAudioDialog = builder.create();

            recordAudioDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    if (voiceTimer != null) {
                        voiceTimer.cancel();
                        voiceTimer = null;
                    }
                }
            });

        }
        recordAudioDialog.show();
        Window window = recordAudioDialog.getWindow();
        if (window != null) {
            window.setBackgroundDrawableResource(android.R.color.transparent);
            WindowManager.LayoutParams attributes = window.getAttributes();
            attributes.width = ScreenUtils.getScreenWidth() / 4 * 3;
            attributes.dimAmount = 0;
            window.setAttributes(attributes);
            View root = window.getDecorView().findViewById(R.id.ll_root);
            GradientDrawable gradientDrawable = (GradientDrawable) root.getBackground();
            gradientDrawable.setColor(Color.parseColor("#80000000"));
            ImageView iv = root.findViewById(R.id.iv);
            iv.setImageResource(R.mipmap.icon_chat_mic);
            LinearLayout llVoice = root.findViewById(R.id.ll_voice);
            llVoice.setVisibility(View.VISIBLE);
            for (int i = 0; i < voiceLevel; i++) {
                if (i != voiceLevel - 1) {
                    llVoice.getChildAt(i).setBackgroundColor(Color.parseColor("#80FAFAFA"));
                }
            }
            TextView tvTips = root.findViewById(R.id.tv_tips);
            Drawable drawable = getResources().getDrawable(R.mipmap.icon_chat_audio_withdraw);
            drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
            tvTips.setCompoundDrawables(drawable, null, null, null);
            tvTips.setText("手指上划，取消发送");
        }

        voiceTimer = new Timer();
        voiceTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (!cancelRecordAudio) {
                            if (mediaRecorder != null) {
                                int ratio = mediaRecorder.getMaxAmplitude() / 600;
                                if (recordAudioDialog != null && recordAudioDialog.isShowing()) {
                                    double log10 = Math.log10(ratio);
                                    int db = (int) (20 * log10);

                                    if (db < minVoice) {
                                        db = minVoice;
                                    } else if (db > (7 * minVoice)) {
                                        db = 7 * minVoice;
                                    }

                                    int voice = db / minVoice;

                                    Window window = recordAudioDialog.getWindow();
                                    if (window != null) {
                                        View root = window.getDecorView().findViewById(R.id.ll_root);
                                        LinearLayout llVoice = root.findViewById(R.id.ll_voice);
                                        if (llVoice.getVisibility() == View.VISIBLE) {
                                            for (int i = 0; i < voiceLevel; i++) {
                                                llVoice.getChildAt(i).setBackgroundColor(voiceLevel - i > voice ? Color.parseColor("#80FAFAFA") : Color.WHITE);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }, 200, 200);
    }

    private void recordFinish() {
        if (recordAudioDialog != null && recordAudioDialog.isShowing()) {
            recordAudioDialog.dismiss();
        }
        tvRecordAudio.setText("按住说话");
        if (mediaRecorder != null) {
            try {
                mediaRecorder.stop();
                mediaRecorder.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
            mediaRecorder = null;
        }
        Object tag = tvRecordAudio.getTag();
        if (tag != null) {
            try {
                String path = String.valueOf(tag);
                File file = new File(path);
                if (file.exists()) {
                    if (!cancelRecordAudio) {
                        int duration = AudioManager.getInstance().getDuration(path);
                        if (duration < 1000) {
                            showRecordAudioTipsDialog();
                        } else {
                            String content = Base64.encodeToString(FileIOUtils.readFile2BytesByStream(file), Base64.DEFAULT);
                            ChatMessage chatMessage = new ChatMessage(chat, userInfoManager.getLoginUserInfo(), MessageType.CHAT_AUDIO, content);
                            chatMessage.setDuration((int) Math.ceil(duration / 1000F));
                            chatMessage.setAudioCachePath(path);
                            sendMessage(chatMessage);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            tvRecordAudio.setTag(null);
        }
    }

    private void showRecordAudioTipsDialog() {
        if (recordAudioTipsDialog == null) {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            View root = inflater.inflate(R.layout.dialog_chat_record_audio_tips, null);
            GradientDrawable gradientDrawable = new GradientDrawable();
            gradientDrawable.setColor(Color.parseColor("#80000000"));
            gradientDrawable.setCornerRadius(20);
            root.setBackground(gradientDrawable);

            builder.setView(root);
            recordAudioTipsDialog = builder.create();
        }
        recordAudioTipsDialog.show();
        Window window = recordAudioTipsDialog.getWindow();
        if (window != null) {
            window.setBackgroundDrawableResource(android.R.color.transparent);
            WindowManager.LayoutParams attributes = window.getAttributes();
            attributes.width = ScreenUtils.getScreenWidth() / 4 * 3;
            attributes.dimAmount = 0;
            window.setAttributes(attributes);
        }
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (recordAudioTipsDialog != null && recordAudioTipsDialog.isShowing()) {
                            recordAudioTipsDialog.dismiss();
                        }
                    }
                });
            }
        }, 500);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(ErrorMessageEvent event) {
        Message message = event.getMessage();
        switch (event.getErrorCode()) {
            case 11000:
                if (message != null) {
                    String msgId = message.getMsgId();
                    ArrayList<ChatMessage> chatMessages = adapter.getDatas();
                    int size = chatMessages.size();
                    for (int i = 0; i < size; i++) {
                        ChatMessage chatMessage = chatMessages.get(i);
                        if (chatMessage.getMsgId().equals(msgId)) {
                            chatMessage.setChatMessageStatus(ChatMessageStatus.FAILURE);
                            adapter.notifyItemChanged(i);
                            break;
                        }
                    }
                }
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(ReceiveMessageEvent event) {
        update(event.getMessage());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(SendMessageEvent event) {
        update(event.getMessage());
    }

    private void update(Message message) {
        if (message != null) {
            MessageType messageType = message.getMessageType();
            if (messageType == MessageType.GROUP_CHAT_NOTICE) {
                showGroupChatNotice((ChatMessage) message);
            }

            if (messageType.isChatMessage()) {
                ChatMessage chatMessage = (ChatMessage) message;
                ArrayList<ChatMessage> datas = adapter.getDatas();
                int index = -1;

                for (int i = 0; i < datas.size(); i++) {
                    if (datas.get(i).getMsgId().equals(chatMessage.getMsgId())) {
                        index = i;
                    }
                }
                if (index != -1) {
                    datas.set(index, chatMessage);
                    adapter.notifyItemChanged(index);
                } else {
                    if (chatMessage.getChatId().equals(chat.getChatId())) {
                        chatMessage.setRead(true);
                        MessageManager.update(chatMessage);

                        adapter.loadMore(chatMessage);
                        recyclerView.scrollToPosition(adapter.getItemCount() - 1);

                        switch (messageType) {
                            case GROUP_CHAT_MEMER_ADD:
                            case GROUP_CHAT_MEMER_REMOVE:
                            case GROUP_CHAT_TABOO:
                                init();
                                break;
                            case GROUP_CHAT_TABOO_RELIEVE:
                                llOperate.setVisibility(View.VISIBLE);
                                break;
                            case GROUP_CHAT_DISMISS:
                                llOperate.setVisibility(View.GONE);
                                initOptions(false);
                                break;
                        }
                    }
                }
            }
        }
    }

    private void showGroupChatNotice(ChatMessage chatMessage) {
        if (chatMessage != null && !chatMessage.isRead()) {
            tvGroupChatNotice.setVisibility(View.VISIBLE);
            tvGroupChatNotice.setText("群公告：" + chatMessage.getContent());
            tvGroupChatNotice.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    chatMessage.setRead(true);
                    MessageManager.update(chatMessage);

                    HashMap<String, Object> params = new HashMap<>();
                    params.put("id", chat.getRecipientId());
                    requestManager.request(requestManager.mMessageRetrofitService.getGroupChatSetting(RequestManager.getJsonRequestBody(params)),
                            new BaseObserverImpl<GroupChatSetting>() {
                                @Override
                                public void onSuccess(GroupChatSetting groupChatSetting) {
                                    super.onSuccess(groupChatSetting);
                                    tvGroupChatNotice.setVisibility(View.GONE);
                                    GroupChatNoticeActivity.show(mContext, groupChatSetting);
                                }
                            });
                }
            });
        }
    }
}







































